home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Utilities / uupc 3.1 / (uupc π) / ctbio.c next >
Encoding:
C/C++ Source or Header  |  1994-09-05  |  21.7 KB  |  943 lines  |  [TEXT/KAHL]

  1. /*
  2.  *    This is a replacement module for sio.c in Sak Wathanasin's 1989 distribution
  3.  *    of uupc for the Mac. It uses a CTB connection tool for "serial i/o".
  4.  *
  5.  *    In order to preserve the interface, some function declarations kept
  6.  *    serial-specific parameters which are now unused.
  7.  *
  8.  *  Originally written by Roger Pantos.  Modified by Dave Platt to fit into
  9.  *  uupc 3.1.
  10.  */
  11.  
  12. #include "dcp.h"
  13.  
  14. #include <Connections.h>
  15. #include <CommResources.h>
  16. #include <Serial.h>
  17. #include <GestaltEqu.h>
  18.  
  19. #include "ctbio.proto.h"
  20.  
  21. const long    kBufferSize = 2048;
  22.  
  23. ConnectionHandler ctbHandler = {
  24.     CTBIOInit,
  25.     CTBIOInBuffer,
  26.     CTBIOOutBuffer,
  27.     CTBIOSpeed,
  28.     CTBIOHandshake,
  29.     CTBIOSetting,
  30.     CTBIOClose,
  31.     CTBIOSetFlowCtl,
  32.     CTBIOAllowInterrupts,
  33.     CTBIOInterrupt,
  34.     CTBIOPurge,
  35.     CTBIOPutchar,
  36.     CTBIOWrite,
  37.     CTBIOAvail,
  38.     CTBIOWStr,
  39.     CTBIORead,
  40.     CTBIOIdle,
  41.     CTBIOEvent,
  42.     CTBIOBreak,
  43.     CTBIOSetParity
  44. };
  45.  
  46. static int allowInterrupts = FALSE;
  47. static int interruptOccurred = FALSE;
  48.  
  49. CMBufferSizes    buffSizes = {
  50.     0L, 0L,
  51.     0L, 0L,
  52.     0L, 0L,
  53.     0L, 0L,
  54. };    
  55.  
  56. ConnHandle    gSerConHdl;
  57. extern SysEnvRec SysEnv;
  58. extern int settingsFileVRefNum;
  59. extern long int settingsFileDirID;
  60. extern int useHardwareFlowControl;
  61.  
  62. volatile int serialIOBusy, serialIOLock, serialIOCompleted;
  63.  
  64. static char *inbuf, *outbuf;
  65. static long inbufSize, outbufSize;
  66. static long writeCount, writeBase, writeOrigin;
  67. static long foregroundWrites, backgroundWrites;
  68. static long bytesActuallyWritten;
  69. static CMErr serialIOError;
  70. static int closeCompleted;
  71. static int connectionShutDown;
  72. static int asynchronous;
  73.  
  74. static enum {
  75.   fully_synchronous,
  76.   asynchronous_foreground,
  77.   asynchronous_fore_background
  78. } synchrony;
  79.  
  80. #define NOWAIT
  81. #define NOWAITWRITE
  82. #define QUIET
  83.  
  84. static void CTBIOEndAction(ConnHandle gSerConHdl)
  85. {
  86.     writeCount -= bytesActuallyWritten;
  87.     writeOrigin = (writeOrigin + bytesActuallyWritten) % outbufSize;
  88. }
  89.  
  90. pascal static void CTBIOOpenCompletion(ConnHandle gSerConHdl)
  91. {
  92.     long savedA5;
  93.     savedA5 = SetCurrentA5();
  94.     SetA5((**gSerConHdl).userData);
  95.     serialIOError = (**gSerConHdl).errCode;
  96.     SetA5(savedA5);
  97.     return;
  98. }
  99.  
  100. pascal static void CTBIOCloseCompletion(ConnHandle gSerConHdl)
  101. {
  102.     long savedA5;
  103.     savedA5 = SetCurrentA5();
  104.     SetA5((**gSerConHdl).userData);
  105.     closeCompleted = 1;
  106.     SetA5(savedA5);
  107.     return;
  108. }
  109.  
  110.  
  111.  
  112. pascal static void CTBIOCompletion(ConnHandle gSerConHdl)
  113. {
  114.     long savedA5;
  115.     long length, toEndOfBuffer;
  116.     CMErr cmErr;
  117.     savedA5 = SetCurrentA5();
  118.     SetA5((**gSerConHdl).userData);
  119.     if (outbuf) {
  120.         bytesActuallyWritten = (**gSerConHdl).asyncCount[cmDataOut];
  121.         if (serialIOLock || synchrony != asynchronous_fore_background) {
  122.             serialIOCompleted = 1;
  123.         } else {
  124.             CTBIOEndAction(gSerConHdl);
  125.             if (writeCount > 0) {
  126.                 length = writeCount;
  127.                 toEndOfBuffer = outbufSize - writeOrigin;
  128.                 if (length > toEndOfBuffer) length = toEndOfBuffer;
  129.                 backgroundWrites += length;
  130.                 cmErr = CMWrite( gSerConHdl, outbuf + writeOrigin, &length, cmData, TRUE, (ProcPtr) CTBIOCompletion, -1L, 0);
  131.                 if (cmErr != noErr) {
  132.                     serialIOBusy = 0;
  133.                     serialIOError = cmErr;
  134.                 }
  135.             } else {
  136.                 serialIOBusy = 0;
  137.             }
  138.         }
  139.     } else {
  140.         serialIOBusy = 0;
  141.     }
  142.     SetA5(savedA5);
  143.     return;
  144. }
  145.  
  146. int CTBIOPush()
  147. {
  148.     long int length, toEndOfBuffer;
  149.     CMErr cmErr;
  150.     if (!gSerConHdl) {
  151.         return 0;
  152.     }
  153.     CMIdle(gSerConHdl);
  154.     if (serialIOCompleted) {
  155.         serialIOCompleted = 0;
  156.         serialIOBusy = 0;
  157.         printmsg(12, "Do endaction, %ld bytes written", bytesActuallyWritten);
  158.         CTBIOEndAction(gSerConHdl);
  159.     }
  160.     if (synchrony != fully_synchronous && (!serialIOBusy && writeCount > 0)) {
  161.         length = writeCount;
  162.         toEndOfBuffer = outbufSize - writeOrigin;
  163.         if (length > toEndOfBuffer) length = toEndOfBuffer;
  164.         serialIOBusy = 1;
  165.         printmsg(12, "Start write, %ld bytes", length);
  166.         foregroundWrites += length;
  167.         cmErr = CMWrite( gSerConHdl, outbuf + writeOrigin, &length, cmData, TRUE, (ProcPtr) CTBIOCompletion, -1L, 0);
  168.         if (cmErr != noErr) {
  169.             serialIOBusy = 0;
  170.             connectionShutDown = TRUE;
  171.             writeCount = 0;
  172.             if (cmErr == cmNotOpen) {
  173.                 printmsg(0, "Connection closed");
  174.             } else {
  175.                 printmsg(0, "CMWrite error %d", cmErr);
  176.             }
  177.             return cmErr;
  178.         }
  179.     }
  180.     return 0;
  181. }
  182.  
  183. static void CTBIOWaitOne()
  184. {
  185.     CMIdle(gSerConHdl);
  186.     CTBIOPush();
  187.   if (Check_Events(0)) {
  188.     if (Main_State == Abort_Program)  {
  189.             CMClose( gSerConHdl, FALSE, NULL, -1L, FALSE);
  190.             CMDispose( gSerConHdl);
  191.         exit(-1);
  192.     }
  193.   }
  194. }
  195.  
  196. void CTBIOWait()
  197. {
  198.     do {
  199.         printmsg(12, "busy %d, completed %d, count %d, lock %d", serialIOBusy, serialIOCompleted,
  200.          writeCount, serialIOLock);
  201.         CTBIOWaitOne();
  202.     } while (serialIOBusy);
  203. }
  204.  
  205. int CTBInit()
  206. {
  207.     static int initted = 0;
  208.     OSErr errCode;
  209.     if (!initted) {
  210.         if (    (errCode = InitCTBUtilities()) || (errCode = InitCRM()) || 
  211.                 (errCode = InitCM()))
  212.         {
  213.             printmsg( 0, "CTBInit: Can't initialize Connection Manager, error %d", errCode );
  214.             return 1;
  215.         }
  216.         initted = 1;
  217.     }
  218.     return 0;
  219. }
  220.  
  221. void CTBAddToMenu(MenuHandle theMenu)
  222. {
  223.     int i;
  224.     if ((i = HOpenResFile(settingsFileVRefNum, settingsFileDirID, "\pUUPC Settings", fsRdPerm)) == -1) {
  225.         printmsg(0, "Can't open \"UUPC Settings\" to load CTB configs" );
  226.         return;
  227.     }
  228.   AddResMenu(theMenu,'Cónn');
  229.     CloseResFile(i);
  230. }
  231.  
  232.  
  233. int CTBIsNamedConfig(char *configName)
  234. {
  235.     Handle dataHandle;
  236.     int i;
  237.     if ((i = HOpenResFile(settingsFileVRefNum, settingsFileDirID, "\pUUPC Settings", fsRdPerm)) == -1) {
  238.         printmsg(0, "Can't open \"UUPC Settings\" to read configuration" );
  239.         return FALSE;
  240.     }
  241.     dataHandle =  GetNamedResource('Cónn', configName);
  242.     if (dataHandle) {
  243.         CloseResFile(i);
  244.         return TRUE;
  245.     } else {
  246.         CloseResFile(i);
  247.         return FALSE;
  248.     }
  249. }
  250.  
  251. ConnHandle CTBLoadConfig(char *configName)
  252. {
  253.     Handle dataHandle;
  254.     ConnHandle connHandle;
  255.     short cProcID;
  256.     char *configString;
  257.     int configChars;
  258.     char bogusName[256];
  259.     int i;
  260.     Str255 defaultTool;
  261.     OSErr err;
  262.     if (CTBInit()) {
  263.         return NULL;
  264.     }
  265.     if ((i = HOpenResFile(settingsFileVRefNum, settingsFileDirID, "\pUUPC Settings", fsRdPerm)) == -1) {
  266.         printmsg(0, "Can't open \"UUPC Settings\" to read configuration" );
  267.         return NULL;
  268.     }
  269.     dataHandle =  GetNamedResource('Cónn', configName);
  270.     if (dataHandle) {
  271.         DetachResource(dataHandle);
  272.     }
  273.     CloseResFile(i);
  274.     if (!dataHandle) {
  275.         if (strncmp(configName, "\pDefault", 8) != 0) {
  276.             strncpy(bogusName, configName+1, 64);
  277.             bogusName[configName[0]] = '\0';
  278.             printmsg(0, "Can't load CTB configuration %s", bogusName);
  279.             return NULL;
  280.         }
  281.         err = CRMGetIndToolName('cbnd', 1, defaultTool);
  282.         if (err != noErr) {
  283.             printmsg(0, "Can't find any Connection Tools!\n");
  284.             return NULL;
  285.         }
  286.         dataHandle = NewHandle(defaultTool[0] + 3);
  287.         if (!dataHandle) {
  288.             return NULL;
  289.         }
  290.         HLock(dataHandle);
  291.         memcpy(*dataHandle, (char *) defaultTool, defaultTool[0] + 1);
  292.         (*dataHandle)[defaultTool[0] + 1] = 0;
  293.         (*dataHandle)[defaultTool[0] + 2] = 0;
  294.         HUnlock(dataHandle);
  295.     }
  296.     MoveHHi(dataHandle);
  297.     HLock(dataHandle);
  298.     if ( (cProcID = CMGetProcID( (StringPtr) *dataHandle)) == -1) {
  299.         PtoCstr((StringPtr) *dataHandle);
  300.         printmsg(0, "CTBLoadConfig:  can't get procid for %s", *dataHandle);
  301.         ReleaseResource(dataHandle);
  302.         return NULL;
  303.     }
  304. #ifdef QUIET
  305.     if ( !(connHandle = CMNew( cProcID, (debuglevel == 0) ? cmQuiet : 0L, buffSizes, 0L, 0L)))
  306. #else
  307.     if ( !(connHandle = CMNew( cProcID, 0, buffSizes, 0L, 0L)))
  308. #endif
  309.     {
  310.         PtoCstr((StringPtr) *dataHandle);
  311.         printmsg(0, "CTBLoadConfig: Can't open a new %s connection", *dataHandle);
  312.         ReleaseResource(dataHandle);
  313.         return NULL;
  314.     }
  315.     configString = (char *) (*dataHandle + **dataHandle + 1);
  316.     if (*configString != '\0') {
  317.         configChars = CMSetConfig(connHandle, configString);
  318.         if (configChars != cmNoErr) {
  319.             if (configChars == -1) {
  320.                 printmsg(0, "CTBLoadConfig: unknown CTB error %d", configChars);
  321.             } else if (configChars < 0) {
  322.                 printmsg(0, "CTBLoadConfig: O/S error %d", configChars);
  323.             } else {
  324.                 printmsg(0, "CTBLoadConfig: config parse error at %s", configChars + configString);
  325.             }
  326.             ReleaseResource(dataHandle);
  327.             return NULL;
  328.         }
  329.     }
  330.     ReleaseResource(dataHandle);
  331.     return connHandle;
  332. }
  333.  
  334.  
  335. void CTBPurgeConfig(char *configName)
  336. {
  337.     Handle dataHandle;
  338.     int i;
  339.     if ((i = HOpenResFile(settingsFileVRefNum, settingsFileDirID, "\pUUPC Settings", fsRdWrPerm)) == -1) {
  340.         printmsg(0, "Can't open \"UUPC Settings\" to remove configuration" );
  341.         return;
  342.     }
  343.     dataHandle =  GetNamedResource('Cónn', configName);
  344.     if (dataHandle) {
  345.         RmveResource(dataHandle);
  346.     }
  347.     CloseResFile(i);
  348. }
  349.  
  350. void CTBSaveConfig(char *configName, ConnHandle connHandle)
  351. {
  352.     Str255 toolName;
  353.     Ptr configString;
  354.     Handle configHandle;
  355.     int oldResFile, newID;
  356.     OSErr osErr;
  357.     int i;
  358.     CMGetToolName((**connHandle).procID, toolName);
  359.     PtrToHand(toolName, &configHandle, toolName[0]+1);
  360.     configString = CMGetConfig(connHandle);
  361.     if (!configString) {
  362.         printmsg(0, "Oops!  Couldn't save configuration!");
  363.         CMDispose( connHandle );
  364.         DisposHandle(configHandle);
  365.         return;
  366.     }
  367.     PtrAndHand(configString, configHandle, strlen(configString)+1);
  368.     DisposPtr(configString);
  369.     if ((i = HOpenResFile(settingsFileVRefNum, settingsFileDirID, "\pUUPC Settings", fsRdWrPerm)) == -1) {
  370.         printmsg(0, "Can't open \"UUPC Settings\" to save configuration" );
  371.         return;
  372.     }
  373.     newID = UniqueID('Cónn');
  374.     osErr = ResError();
  375.     AddResource((Handle) configHandle, 'Cónn', newID, configName);
  376.     osErr = ResError();
  377.     CloseResFile(i);
  378. }
  379.  
  380. CTBIOInit ( char * whichport, char * speed, char * phone )
  381. {
  382. Point    where;
  383. short    errCode=FALSE, cprocID;
  384. CMBufferSizes    sizes;
  385. CMStatFlags        flags;
  386. int oldResFile, newID;
  387. int incoming;
  388. OSErr osErr;
  389. Ptr configString;
  390. Handle configHandle;
  391. Str255 connString;
  392. char command[256], *cmdStart;
  393. long int minutes_to_sleep;
  394. long currentA5;
  395.  
  396.     if ((connectionManagerGestalt & (1L << gestaltConnMgrPresent)) == 0) {
  397.         printmsg( 0, "CTBIOInit: Connection Manager not available" );
  398.         return -1;
  399.     }
  400.         
  401.     if (CTBInit()) {
  402.         return -1;
  403.     }
  404.     
  405.     strcpy((char *) connString, whichport);
  406.     
  407.     CtoPstr((char *) connString);
  408.     
  409.     gSerConHdl = CTBLoadConfig( (char *) connString );
  410.     
  411.     if (!gSerConHdl) {
  412.         printmsg(0, "Cannot load CTB configuration '%s'", whichport);
  413.         return -1;
  414.     }
  415.  
  416.     printmsg(2, "CTB configuration %s loaded", whichport);
  417.     
  418.     synchrony = asynchronous_fore_background;
  419.     
  420.     if (strlen(speed) > 0 && strcmp(speed, "\"\"") != 0 && strncmp(speed, "-", 1) != 0) {
  421.         printmsg(2, "CTB options: %s", speed);
  422.         if (strchr(speed, ' ') == NULL && isdigit(*speed)) {
  423.             strcpy(command, "Baud ");
  424.             strncat(command, speed, 128);
  425.             cmdStart = command;
  426.             errCode = CMSetConfig(gSerConHdl, command);
  427.         } else {
  428.             cmdStart = speed;
  429.             errCode = CMSetConfig(gSerConHdl, speed);
  430.         }
  431.         if (errCode != cmNoErr) {
  432.             if (errCode < 0) {
  433.                 printmsg(0, "CTB o/s error %d", errCode);
  434.             } else if (errCode == -1) {
  435.                 printmsg(0, "CTB unknown error");
  436.             } else {
  437.                 printmsg(0, "CTB parse error at: %s", cmdStart + errCode);
  438.             }
  439.             goto bailout;
  440.         }
  441.     }
  442.     
  443.     if (strcmp(speed, "-sync") == 0) {
  444.         synchrony = fully_synchronous;
  445.     } else if (strcmp(speed, "-async") == 0) {
  446.         synchrony = asynchronous_foreground;
  447.     } else if (strncmp(speed, "-background", 5) == 0) {
  448.         synchrony = asynchronous_fore_background;
  449.     }
  450.     
  451.     if (synchrony == fully_synchronous) {
  452.         asynchronous = FALSE;
  453.     } else {
  454.         asynchronous = TRUE;
  455.     }
  456.  
  457.     if (phone && strlen(phone) > 0 && strcmp(phone, "\"\"") != 0 && strcmp(phone, "-") != 0 &&
  458.      strcmp(phone, "@") != 0) {
  459.         printmsg(2, "CTB phone: %s", phone);
  460.         strcpy(command, "PhoneNumber \"");
  461.         strncat(command, phone, 128);
  462.         strcat(command, "\"");
  463.         errCode = CMSetConfig(gSerConHdl, command);
  464.         if (errCode != cmNoErr) {
  465.             if (errCode < 0) {
  466.                 printmsg(0, "CTB o/s error %d", errCode);
  467.             } else if (errCode == -1) {
  468.                 printmsg(0, "CTB unknown error");
  469.             } else {
  470.                 printmsg(0, "CTB parse error at: %s", command + errCode);
  471.             }
  472.             goto bailout;
  473.         }
  474.     }
  475.  
  476.     currentA5 = SetCurrentA5();
  477.     CMSetUserData(gSerConHdl, currentA5);
  478.     
  479.     serialIOBusy = 0;
  480.     serialIOLock = 0;
  481.     serialIOCompleted = 0;
  482.     serialIOError = cmNoErr;
  483.     inbuf = outbuf = NULL;
  484.     inbufSize = outbufSize = 0;
  485.     writeCount = writeBase = writeOrigin = 0;
  486.     foregroundWrites = backgroundWrites = 0;
  487.     currentConnection = &ctbHandler;
  488.     
  489.     if (strcmp(phone, "@") == 0) {
  490.         incoming = TRUE;
  491.         sscanf(sleeptime, "%ld", &minutes_to_sleep);
  492.         if (minutes_to_sleep < 1) minutes_to_sleep = 1;
  493.         printmsg(2, "Listening for inbound call, %ld-minute timeout", minutes_to_sleep);
  494.         errCode = CMListen( gSerConHdl, asynchronous, (ProcPtr) CTBIOOpenCompletion, minutes_to_sleep * 3600L);
  495.     } else {
  496.         incoming = FALSE;
  497.         errCode = CMOpen( gSerConHdl, asynchronous, (ProcPtr) CTBIOOpenCompletion, -1L);
  498.     }
  499.     
  500.     if (errCode) {
  501.         printmsg(0, "Connection Manager error %d", errCode);
  502.         currentConnection = (ConnectionHandler *) NULL;
  503.         CMDispose( gSerConHdl);
  504.         return -1;
  505.     }
  506.     
  507.     allowInterrupts = TRUE;
  508.     interruptOccurred = FALSE;
  509.     connectionShutDown = FALSE;
  510.     
  511.     while (1) {
  512.         CMIdle(gSerConHdl);
  513.         errCode = CMStatus(gSerConHdl, sizes, &flags);
  514.         if (errCode != noErr) goto bailout;
  515.         if (flags & cmStatusOpen) break;
  516.         if (flags & cmStatusIncomingCallPresent) {
  517.             printmsg(0, "Incoming call!");
  518.             errCode = CMAccept(gSerConHdl, TRUE);
  519.             if (errCode != 0) {
  520.                 printmsg(0, "Incoming call could not be accepted, error %d", errCode);
  521.                 goto bailout;
  522.             }
  523.             break;
  524.         }
  525.         if (!(flags & (cmStatusOpening | cmStatusListenPend))) {
  526.             if (serialIOError == cmUserCancel) {
  527.                 Set_Main_State(Cancel_Call);
  528.             } else {
  529.                 printmsg(0, "Connection failed to open, error %d", serialIOError);
  530.             }
  531.             CMAbort(gSerConHdl);
  532.             CMClose(gSerConHdl, FALSE, NULL, -1L, TRUE);
  533.             goto bailout;
  534.         }
  535.       if (Check_Events(6)) {
  536.         if (Main_State == Abort_Program)  {
  537.               CMAbort(gSerConHdl);
  538.               CMClose(gSerConHdl, FALSE, NULL, -1L, FALSE);
  539.                 CMDispose( gSerConHdl);
  540.             exit(-1);
  541.         }
  542.       }
  543.         if (allowInterrupts && interruptOccurred) {
  544.           CMAbort(gSerConHdl);
  545.             goto bailout;
  546.         }
  547.     }
  548.     allowInterrupts = FALSE;
  549.     return 0;
  550. bailout:
  551.     currentConnection = (ConnectionHandler *) NULL;
  552.     CMDispose( gSerConHdl);
  553.     gSerConHdl = NULL;
  554.     return -1;
  555.  
  556. }
  557.  
  558.  
  559. CTBIOInBuffer ( char * buf, int size)
  560. {
  561.     inbuf = buf;
  562.     inbufSize = size;
  563. }
  564.  
  565. CTBIOOutBuffer ( char * buf, int size)
  566. {
  567.     outbuf = buf;
  568.     outbufSize = size;
  569. }
  570.  
  571.  
  572. CTBIOSpeed( char *speed )
  573. {
  574.     char realSpeed[256];
  575.     short errCode;
  576.     strcpy(realSpeed, "Baud ");
  577.     strncat(realSpeed, speed, 20);
  578.     errCode = CMSetConfig(gSerConHdl, realSpeed);
  579.     if (errCode != cmNoErr) {
  580.         if (errCode < 0) {
  581.             printmsg(0, "CTBIOSpeed: O/S error %d", errCode);
  582.         } else if (errCode == -1) {
  583.             printmsg(0, "CTBIOSpeed: Unknown CTB error");
  584.         } else {
  585.             printmsg(0, "CTBIOSpeed: CTB parse error at: %s", speed + errCode);
  586.         }
  587.     }
  588. }
  589.  
  590. CTBIOHandshake(int fInx, int fXOn, int fCTS, int xOn, int xOff)
  591. {
  592. }
  593.  
  594. CTBIOSetting(char *speed, int parity, int stopbits, int databits)
  595. {
  596. }
  597.  
  598. int CTBIOAvail(void)
  599. {
  600. CMBufferSizes    sizes;
  601. CMStatFlags        flags;
  602.  
  603.         if (connectionShutDown) {
  604.             return 0;
  605.         }
  606.         CTBIOPush();
  607.         CMStatus( gSerConHdl, sizes, &flags);
  608.         return ( sizes[ cmDataIn]) ;
  609. }
  610.  
  611. CTBIOWStr(char *st)
  612. {
  613.     return CTBIOWrite ( st, strlen(st)) ;
  614. }
  615.  
  616. int CTBIOSetFlowCtl(int software, int hardware)
  617. {
  618.     if (hardware) {
  619.         (void) CMSetConfig(gSerConHdl, "Handshake DTR&CTS");
  620.     } else if (software) {
  621.         (void) CMSetConfig(gSerConHdl, "Handshake XON/XOFF");
  622.     } else {
  623.         (void) CMSetConfig(gSerConHdl, "Handshake None");
  624.     }
  625. }
  626.  
  627. int CTBIOPutchar(char ch)
  628. {
  629.     return CTBIOWrite(&ch, 1);
  630. }
  631.  
  632. int CTBIOAllowInterrupts(int flag)
  633. {
  634.     int oldFlag;
  635.     oldFlag = allowInterrupts;
  636.     allowInterrupts = flag;
  637.     interruptOccurred &= flag;
  638.     return oldFlag;
  639. }
  640.  
  641. CTBIOInterrupt(void)
  642. {
  643.     interruptOccurred = TRUE;
  644. }
  645.  
  646. CTBIOClose ( dtr )
  647. {
  648.     CMErr cmErr;
  649.  
  650.     if ( gSerConHdl) {
  651.         printmsg(2, "Flushing connection");
  652.         CMIOKill( gSerConHdl, cmDataIn);
  653.         CMIOKill( gSerConHdl, cmDataOut);
  654.         CMReset(gSerConHdl);
  655.         closeCompleted = 0;
  656.         printmsg(2, "Closing connection");
  657.         cmErr = CMClose( gSerConHdl, asynchronous, (ProcPtr) CTBIOCloseCompletion, -1L, TRUE);
  658.         if (asynchronous) {
  659.             while (cmErr == noErr && !closeCompleted) {
  660.                 short errCode;
  661.                 CMBufferSizes    sizes;
  662.                 CMStatFlags        flags;
  663.                 CMIdle(gSerConHdl);
  664.                 cmErr = CMStatus(gSerConHdl, sizes, &flags);
  665.                 (void) Check_Events(6);
  666.                 if (Main_State == Abort_Program) {
  667.                     CMDispose( gSerConHdl);        
  668.                     exit(-1);
  669.                 }
  670.     #ifdef NOTDEF
  671.                 if (!(flags & (cmStatusOpen | cmStatusOpening))) {
  672.                     break;
  673.                 }
  674.     #endif
  675.             }
  676.         }
  677.         printmsg(1, "%ld bytes written mainline, %ld bytes written from interrupt handler",
  678.             foregroundWrites, backgroundWrites);
  679.         CMDispose( gSerConHdl);        
  680.         gSerConHdl = NULL;
  681.         currentConnection = (ConnectionHandler *) NULL;
  682.     }
  683. }
  684.  
  685.  
  686. CTBIOPurge ( void)
  687. {
  688.     CMIOKill( gSerConHdl, cmDataIn);
  689.     CMIOKill( gSerConHdl, cmDataOut);
  690. }
  691.  
  692.  
  693. /* timeout is in tenths of a second */
  694. int CTBIORead ( char *byt, int mincount, int maxcount, long int tenths )
  695. {
  696. long            endTime, count;
  697. CMBufferSizes    sizes;
  698. CMStatFlags        flags;
  699. CMFlags            eomFlag;
  700.  
  701.     endTime = TickCount() + 6 * tenths;
  702.     
  703.     do {
  704.       if (Check_Events(0)) {
  705.         if (Main_State == Abort_Program)  {
  706.                 CTBIOPurge();
  707.                 CMClose( gSerConHdl, FALSE, NULL, -1L, FALSE);
  708.                 CMDispose( gSerConHdl);
  709.             exit(-1);
  710.         }
  711.       }
  712.         /* check if we have enough bytes in read buffer */
  713.         
  714.         if (connectionShutDown) {
  715.             return -1;
  716.         }
  717.         CTBIOPush(); /* cmIdle and push unwritten output */
  718.         CMStatus( gSerConHdl, sizes, &flags);
  719.         if ( sizes[ cmDataIn] >= mincount) {
  720.             count = maxcount;
  721.             CMRead(  gSerConHdl, byt, &count, cmData, FALSE, NULL, -1, &eomFlag);
  722.             return (int) count;
  723.         }
  724.         if (allowInterrupts && interruptOccurred) {
  725.             return -1;
  726.         }
  727.     } while ( TickCount() < endTime);
  728.     
  729.     return (int) sizes[ cmDataIn];        /* return max available (or -1?) */
  730. }
  731.  
  732. int CTBIOWrite ( char *buf, int count )
  733. {
  734. long    length;
  735. long avail, toWrite, toEndOfBuffer;
  736. CMErr cmErr;
  737.  
  738.     if (connectionShutDown) {
  739.         return 1;
  740.     }
  741.     if (outbuf && asynchronous) {
  742.         while (count > 0) {
  743.             serialIOLock = 1;
  744.             avail = outbufSize - writeCount;
  745.             if (avail == 0) {
  746.                 serialIOLock = 0;
  747.                 CTBIOWaitOne();
  748.                 continue;
  749.             }
  750.             if (count > 0) {
  751.                 toEndOfBuffer = outbufSize - writeBase;
  752.                 toWrite = count;
  753.                 if (toWrite > avail) toWrite = avail;
  754.                 if (toWrite > toEndOfBuffer) toWrite = toEndOfBuffer;
  755.                 memcpy(outbuf + writeBase, buf, toWrite);
  756.                 writeBase = (writeBase + toWrite) % outbufSize;
  757.                 buf += toWrite;
  758.                 writeCount += toWrite;
  759.                 count -= toWrite;
  760.             }
  761.             serialIOLock = 0;
  762.             cmErr = CTBIOPush();
  763.             if (cmErr) {
  764.                 return cmErr;
  765.             }
  766. #ifdef NOTDEF
  767.             if (serialIOCompleted) {
  768.                 serialIOCompleted = 0;
  769.                 serialIOBusy = 0;
  770.                 CTBIOEndAction(gSerConHdl);
  771.             }
  772.             if (!serialIOBusy && writeCount > 0) {
  773.                 length = writeCount;
  774.                 serialIOBusy = 1;
  775.                 printmsg(12, "Start write, %ld bytes", length);
  776.                 foregroundWrites += length;
  777.                 cmErr = CMWrite( gSerConHdl, outbuf + writeOrigin, &length, cmData, TRUE, (ProcPtr) CTBIOCompletion, -1L, 0);
  778.                 if (cmErr != noErr) {
  779.                     serialIOBusy = 0;
  780.                     connectionShutDown = TRUE;
  781.                     if (cmErr == cmNotOpen) {
  782.                         printmsg(0, "Connection closed");
  783.                     } else {
  784.                         printmsg(0, "CMWrite error %d", cmErr);
  785.                     }
  786.                     return 1;
  787.                 }
  788.             }
  789. #endif
  790.         } 
  791.     } else if (asynchronous) {
  792.         serialIOBusy = 1;
  793.         length = count;
  794.         foregroundWrites += length;
  795.         cmErr = CMWrite( gSerConHdl, buf, &length, cmData, TRUE, (ProcPtr) CTBIOCompletion, -1L, 0);
  796.         if (cmErr != noErr) {
  797.             connectionShutDown = TRUE;
  798.             if (cmErr == cmNotOpen) {
  799.                 printmsg(0, "Connection closed");
  800.             } else {
  801.                 printmsg(0, "CMWrite error %d", cmErr);
  802.             }
  803.             return 1;
  804.         }
  805.         CTBIOWait();
  806.     } else {
  807.         length = count;
  808.         foregroundWrites += length;
  809.       if (Check_Events(0)) {
  810.         if (Main_State == Abort_Program)  {
  811.                 CTBIOPurge();
  812.                 CMClose( gSerConHdl, FALSE, NULL, -1L, FALSE);
  813.                 CMDispose( gSerConHdl);
  814.             exit(-1);
  815.         }
  816.       }
  817.         cmErr = CMWrite( gSerConHdl, buf, &length, cmData, FALSE, (ProcPtr) NULL, -1L, 0);
  818.         if (cmErr != noErr) {
  819.             connectionShutDown = TRUE;
  820.             if (cmErr == cmNotOpen) {
  821.                 printmsg(0, "Connection closed");
  822.             } else {
  823.                 printmsg(0, "CMWrite error %d", cmErr);
  824.             }
  825.             return 1;
  826.         }
  827.     }
  828.  
  829.     return 0 /* (int) count */;
  830.     
  831. /*
  832.     Memo to self - should really clean up CTBIOWrite, SIOWrite, putu, swrite, the
  833.     gsendpkt/fsendpkt, and the send-data loop in dcpxfer, to agree on what value a
  834.     low-level-write routine really returns and what it means.  There's some disagreement
  835.     in the code... some routines expect a 0-for-OK-or-nonzero-error-code, some expect
  836.     or provide a bytes-actually-written count, some don't care.  For now, it's the former.
  837.     -- dplatt
  838. */
  839. }
  840.  
  841. CTBIOIdle()
  842. {
  843.     long    length;
  844.     CMErr cmErr;
  845.     if (gSerConHdl) {
  846.         CTBIOPush();
  847.     }
  848. }
  849.  
  850. int CTBIOEvent(EventRecord *anEvent)
  851. {
  852.   WindowPeek theWindow;
  853.   int code;
  854.     if (!gSerConHdl) {
  855.         return 0;
  856.     }
  857.     switch (anEvent->what) {
  858.         case activateEvt:
  859.             theWindow = (WindowPeek) anEvent->message;
  860.             if (gSerConHdl != (ConnHandle) theWindow->refCon) {
  861.                 return 0;
  862.             }
  863.             if (anEvent->modifiers & activeFlag) {
  864.                 CMActivate(gSerConHdl, TRUE);
  865.             } else {
  866.                 CMActivate(gSerConHdl, FALSE);
  867.             }
  868.             return 1;
  869.                     
  870.         case updateEvt:
  871.             theWindow = (WindowPeek) anEvent->message;
  872.             if (gSerConHdl != (ConnHandle) theWindow->refCon) {
  873.                 return 0;
  874.             }
  875.             CMEvent(gSerConHdl, anEvent);
  876.             return 1;
  877.  
  878.         case mouseDown:
  879.         code = FindWindow(anEvent->where,&theWindow);
  880.         switch (code) {
  881.             case inContent:
  882.             case inDrag:
  883.             case inGrow:
  884.             case inGoAway:
  885.                     if (gSerConHdl == (ConnHandle) theWindow->refCon) {
  886.                         CMEvent(gSerConHdl, anEvent);
  887.                         return 1;
  888.                     }
  889.                     break;
  890.                 default:
  891.                     break;
  892.             }
  893.             return 0;
  894.                     
  895.         case osEvt:
  896.             if (((anEvent->message >> 24) & 0xFF) == 1 /* suspend */) {
  897.                 if (anEvent->message & 1 /* resume bit */) {
  898.                     CMActivate(gSerConHdl, TRUE);
  899.                 } else {
  900.                     CMActivate(gSerConHdl, FALSE);
  901.                 }
  902.             }
  903.             return 0;
  904.         
  905.         default:
  906.             return 0;
  907.             
  908.     }
  909. }
  910.  
  911. int CTBIOBreak(int tenths)
  912. {
  913.     CMBreak(gSerConHdl, tenths*2, FALSE, (ProcPtr) NULL);
  914. }
  915.  
  916. int CTBIOSetParity(int dataBitsCode, int parityCode)
  917. {
  918.     OSErr errCode;
  919.     switch (dataBitsCode) {
  920.         case data7:
  921.             errCode = CMSetConfig(gSerConHdl, "DataBits 7");
  922.             break;
  923.         case data8:
  924.             errCode = CMSetConfig(gSerConHdl, "DataBits 8");
  925.             break;
  926.     }
  927.     switch (parityCode) {
  928.         case evenParity:
  929.             errCode = CMSetConfig(gSerConHdl, "Parity Even");
  930.             break;
  931.         case oddParity:
  932.             errCode = CMSetConfig(gSerConHdl, "Parity Odd");
  933.             break;
  934.         case noParity:
  935.             errCode = CMSetConfig(gSerConHdl, "Parity None");
  936.             break;
  937.     }
  938.     return;
  939. }
  940.  
  941.         
  942.     
  943.